import threading

class MMU:
    #Unidad de Administracion de memoria
    def __init__(self, algoritmoDeMemoria): 
        # un algoritmo de memoria puede ser Paginacion o AsignacionContinua
        self.algoritmo = algoritmoDeMemoria
        #se agrego un semaforo para no tener conflictos entre el CPU y el KERNEL 
        #en el momento de utilizar la memoria.
        self.lock = threading.RLock()
        self.manager = None
        
    def setManager(self,manager):
        self.manager = manager
        
    def put(self,pid,listaInstrucciones): #guarda un programa en memoria
        self.lock.acquire()
        #pasamos al MMU por parametro por si hay que hacer swapping
        self.algoritmo.guardaEnMemoria(pid,listaInstrucciones, self.manager) 
        self.lock.release()
    
    def inicializarProgramaParaDisco(self,pid,listaInstrucciones):
        return self.algoritmo.crearDatosParaDisco(pid,listaInstrucciones)
    
    def ponerEnDisco(self,kernel):
        #Delega el trabajo a el algoritmo de memoria
        self.algoritmo.guardaEnDisco(kernel)
        
        
    def leer(self,pcb): 
        self.lock.acquire()
        if pcb.getCurrentInst() ==pcb.getCantInstrucciones():
            # esta modelado el fin del programa como que se ejecutaron una cantidad de instrucciones
            #igual a la cantidad TOTAL de instrucciones que tenia el programa.
            self.lock.release()
            return None #retorno None si el programa termino
        else:
            self.lock.release()
            return self.algoritmo.obtenerInstruccion(pcb,self.manager)
     # Borra el programa de la memoria   
    def eliminarPrograma(self,pcb): 
        self.lock.acquire()
        self.algoritmo.eliminarProgramaDeMemoria(pcb.getIdProgr())
        self.lock.release()